 /*******************************************************************************
  * Copyright (c) 2000, 2007 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
  * Contributors:
  * IBM Corporation - initial API and implementation
  * Michael Williamson (eclipse-bugs@magnaworks.com) - patch (see Bugzilla #92545)
  *******************************************************************************/
 package org.eclipse.ui.forms.widgets;

 import org.eclipse.jface.resource.JFaceResources;
 import org.eclipse.jface.window.Window;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.custom.CCombo;
 import org.eclipse.swt.custom.ScrolledComposite;
 import org.eclipse.swt.events.FocusAdapter;
 import org.eclipse.swt.events.FocusEvent;
 import org.eclipse.swt.events.KeyAdapter;
 import org.eclipse.swt.events.KeyEvent;
 import org.eclipse.swt.events.MouseAdapter;
 import org.eclipse.swt.events.MouseEvent;
 import org.eclipse.swt.events.PaintEvent;
 import org.eclipse.swt.events.PaintListener;
 import org.eclipse.swt.graphics.Color;
 import org.eclipse.swt.graphics.Font;
 import org.eclipse.swt.graphics.GC;
 import org.eclipse.swt.graphics.Point;
 import org.eclipse.swt.graphics.RGB;
 import org.eclipse.swt.graphics.Rectangle;
 import org.eclipse.swt.widgets.Button;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Control;
 import org.eclipse.swt.widgets.Display;
 import org.eclipse.swt.widgets.Event;
 import org.eclipse.swt.widgets.Label;
 import org.eclipse.swt.widgets.Listener;
 import org.eclipse.swt.widgets.Table;
 import org.eclipse.swt.widgets.Text;
 import org.eclipse.swt.widgets.Tree;
 import org.eclipse.swt.widgets.Widget;
 import org.eclipse.ui.forms.FormColors;
 import org.eclipse.ui.forms.HyperlinkGroup;
 import org.eclipse.ui.forms.IFormColors;
 import org.eclipse.ui.internal.forms.widgets.FormUtil;

 /**
  * The toolkit is responsible for creating SWT controls adapted to work in
  * Eclipse forms. In addition to changing their presentation properties (fonts,
  * colors etc.), various listeners are attached to make them behave correctly in
  * the form context.
  * <p>
  * In addition to being the control factory, the toolkit is also responsible for
  * painting flat borders for select controls, managing hyperlink groups and
  * control colors.
  * <p>
  * The toolkit creates some of the most common controls used to populate Eclipse
  * forms. Controls that must be created using their constructors,
  * <code>adapt()</code> method is available to change its properties in the
  * same way as with the supported toolkit controls.
  * <p>
  * Typically, one toolkit object is created per workbench part (for example, an
  * editor or a form wizard). The toolkit is disposed when the part is disposed.
  * To conserve resources, it is possible to create one color object for the
  * entire plug-in and share it between several toolkits. The plug-in is
  * responsible for disposing the colors (disposing the toolkit that uses shared
  * color object will not dispose the colors).
  * <p>
  * FormToolkit is normally instantiated, but can also be subclassed if some of
  * the methods needs to be modified. In those cases, <code>super</code> must
  * be called to preserve normal behaviour.
  *
  * @since 3.0
  */
 public class FormToolkit {
     public static final String KEY_DRAW_BORDER = "FormWidgetFactory.drawBorder"; //$NON-NLS-1$

     public static final String TREE_BORDER = "treeBorder"; //$NON-NLS-1$

     public static final String TEXT_BORDER = "textBorder"; //$NON-NLS-1$

     private int borderStyle = SWT.NULL;

     private FormColors colors;

     private int orientation = Window.getDefaultOrientation();

     // private KeyListener deleteListener;
 private BorderPainter borderPainter;

     private BoldFontHolder boldFontHolder;

     private HyperlinkGroup hyperlinkGroup;

     /* default */
     VisibilityHandler visibilityHandler;

     /* default */
     KeyboardHandler keyboardHandler;

     private class BorderPainter implements PaintListener {
         public void paintControl(PaintEvent event) {
             Composite composite = (Composite) event.widget;
             Control[] children = composite.getChildren();
             for (int i = 0; i < children.length; i++) {
                 Control c = children[i];
                 boolean inactiveBorder = false;
                 boolean textBorder = false;
                 if (!c.isVisible())
                     continue;
                 /*
                  * if (c.getEnabled() == false && !(c instanceof CCombo))
                  * continue;
                  */
                 if (c instanceof Hyperlink)
                     continue;
                 Object flag = c.getData(KEY_DRAW_BORDER);
                 if (flag != null) {
                     if (flag.equals(Boolean.FALSE))
                         continue;
                     if (flag.equals(TREE_BORDER))
                         inactiveBorder = true;
                     else if (flag.equals(TEXT_BORDER))
                         textBorder = true;
                 }
                 if (getBorderStyle() == SWT.BORDER) {
                     if (!inactiveBorder && !textBorder) {
                         continue;
                     }
                     if (c instanceof Text || c instanceof Table
                             || c instanceof Tree)
                         continue;
                 }
                 if (!inactiveBorder
                         && (c instanceof Text || c instanceof CCombo || textBorder)) {
                     Rectangle b = c.getBounds();
                     GC gc = event.gc;
                     gc.setForeground(c.getBackground());
                     gc.drawRectangle(b.x - 1, b.y - 1, b.width + 1,
                             b.height + 1);
                     // gc.setForeground(getBorderStyle() == SWT.BORDER ? colors
 // .getBorderColor() : colors.getForeground());
 gc.setForeground(colors.getBorderColor());
                     if (c instanceof CCombo)
                         gc.drawRectangle(b.x - 1, b.y - 1, b.width + 1,
                                 b.height + 1);
                     else
                         gc.drawRectangle(b.x - 1, b.y - 2, b.width + 1,
                                 b.height + 3);
                 } else if (inactiveBorder || c instanceof Table
                         || c instanceof Tree) {
                     Rectangle b = c.getBounds();
                     GC gc = event.gc;
                     gc.setForeground(colors.getBorderColor());
                     gc.drawRectangle(b.x - 1, b.y - 1, b.width + 1,
                             b.height + 1);
                 }
             }
         }
     }

     private static class VisibilityHandler extends FocusAdapter {
         public void focusGained(FocusEvent e) {
             Widget w = e.widget;
             if (w instanceof Control) {
                 FormUtil.ensureVisible((Control) w);
             }
         }
     }

     private static class KeyboardHandler extends KeyAdapter {
         public void keyPressed(KeyEvent e) {
             Widget w = e.widget;
             if (w instanceof Control) {
                 if (e.doit)
                     FormUtil.processKey(e.keyCode, (Control) w);
             }
         }
     }

     private class BoldFontHolder {
         private Font normalFont;

         private Font boldFont;

         public BoldFontHolder() {
         }

         public Font getBoldFont(Font font) {
             createBoldFont(font);
             return boldFont;
         }

         private void createBoldFont(Font font) {
             if (normalFont == null || !normalFont.equals(font)) {
                 normalFont = font;
                 dispose();
             }
             if (boldFont == null) {
                 boldFont = FormUtil.createBoldFont(colors.getDisplay(),
                         normalFont);
             }
         }

         public void dispose() {
             if (boldFont != null) {
                 boldFont.dispose();
                 boldFont = null;
             }
         }
     }

     /**
      * Creates a toolkit that is self-sufficient (will manage its own colors).
      *
      */
     public FormToolkit(Display display) {
         this(new FormColors(display));
     }

     /**
      * Creates a toolkit that will use the provided (shared) colors. The toolkit
      * will dispose the colors if and only if they are <b>not</b> marked as
      * shared via the <code>markShared()</code> method.
      *
      * @param colors
      * the shared colors
      */
     public FormToolkit(FormColors colors) {
         this.colors = colors;
         initialize();
     }

     /**
      * Creates a button as a part of the form.
      *
      * @param parent
      * the button parent
      * @param text
      * an optional text for the button (can be <code>null</code>)
      * @param style
      * the button style (for example, <code>SWT.PUSH</code>)
      * @return the button widget
      */
     public Button createButton(Composite parent, String text, int style) {
         Button button = new Button(parent, style | SWT.FLAT | orientation);
         if (text != null)
             button.setText(text);
         adapt(button, true, true);
         return button;
     }

     /**
      * Creates the composite as a part of the form.
      *
      * @param parent
      * the composite parent
      * @return the composite widget
      */
     public Composite createComposite(Composite parent) {
         return createComposite(parent, SWT.NULL);
     }

     /**
      * Creates the composite as part of the form using the provided style.
      *
      * @param parent
      * the composite parent
      * @param style
      * the composite style
      * @return the composite widget
      */
     public Composite createComposite(Composite parent, int style) {
         Composite composite = new LayoutComposite(parent, style | orientation);
         adapt(composite);
         return composite;
     }

     /**
      * Creats the composite that can server as a separator between various parts
      * of a form. Separator height should be controlled by setting the height
      * hint on the layout data for the composite.
      *
      * @param parent
      * the separator parent
      * @return the separator widget
      */
     public Composite createCompositeSeparator(Composite parent) {
         final Composite composite = new Composite(parent, orientation);
         composite.addListener(SWT.Paint, new Listener() {
             public void handleEvent(Event e) {
                 if (composite.isDisposed())
                     return;
                 Rectangle bounds = composite.getBounds();
                 GC gc = e.gc;
                 gc.setForeground(colors.getColor(IFormColors.SEPARATOR));
                 if (colors.getBackground() != null)
                     gc.setBackground(colors.getBackground());
                 gc.fillGradientRectangle(0, 0, bounds.width, bounds.height,
                         false);
             }
         });
         if (parent instanceof Section)
             ((Section) parent).setSeparatorControl(composite);
         return composite;
     }

     /**
      * Creates a label as a part of the form.
      *
      * @param parent
      * the label parent
      * @param text
      * the label text
      * @return the label widget
      */
     public Label createLabel(Composite parent, String text) {
         return createLabel(parent, text, SWT.NONE);
     }

     /**
      * Creates a label as a part of the form.
      *
      * @param parent
      * the label parent
      * @param text
      * the label text
      * @param style
      * the label style
      * @return the label widget
      */
     public Label createLabel(Composite parent, String text, int style) {
         Label label = new Label(parent, style | orientation);
         if (text != null)
             label.setText(text);
         adapt(label, false, false);
         return label;
     }

     /**
      * Creates a hyperlink as a part of the form. The hyperlink will be added to
      * the hyperlink group that belongs to this toolkit.
      *
      * @param parent
      * the hyperlink parent
      * @param text
      * the text of the hyperlink
      * @param style
      * the hyperlink style
      * @return the hyperlink widget
      */
     public Hyperlink createHyperlink(Composite parent, String text, int style) {
         Hyperlink hyperlink = new Hyperlink(parent, style | orientation);
         if (text != null)
             hyperlink.setText(text);
         hyperlink.addFocusListener(visibilityHandler);
         hyperlink.addKeyListener(keyboardHandler);
         hyperlinkGroup.add(hyperlink);
         return hyperlink;
     }

     /**
      * Creates an image hyperlink as a part of the form. The hyperlink will be
      * added to the hyperlink group that belongs to this toolkit.
      *
      * @param parent
      * the hyperlink parent
      * @param style
      * the hyperlink style
      * @return the image hyperlink widget
      */
     public ImageHyperlink createImageHyperlink(Composite parent, int style) {
         ImageHyperlink hyperlink = new ImageHyperlink(parent, style
                 | orientation);
         hyperlink.addFocusListener(visibilityHandler);
         hyperlink.addKeyListener(keyboardHandler);
         hyperlinkGroup.add(hyperlink);
         return hyperlink;
     }

     /**
      * Creates a rich text as a part of the form.
      *
      * @param parent
      * the rich text parent
      * @param trackFocus
      * if <code>true</code>, the toolkit will monitor focus
      * transfers to ensure that the hyperlink in focus is visible in
      * the form.
      * @return the rich text widget
      */
     public FormText createFormText(Composite parent, boolean trackFocus) {
         FormText engine = new FormText(parent, SWT.WRAP | orientation);
         engine.marginWidth = 1;
         engine.marginHeight = 0;
         engine.setHyperlinkSettings(getHyperlinkGroup());
         adapt(engine, trackFocus, true);
         engine.setMenu(parent.getMenu());
         return engine;
     }

     /**
      * Adapts a control to be used in a form that is associated with this
      * toolkit. This involves adjusting colors and optionally adding handlers to
      * ensure focus tracking and keyboard management.
      *
      * @param control
      * a control to adapt
      * @param trackFocus
      * if <code>true</code>, form will be scrolled horizontally
      * and/or vertically if needed to ensure that the control is
      * visible when it gains focus. Set it to <code>false</code> if
      * the control is not capable of gaining focus.
      * @param trackKeyboard
      * if <code>true</code>, the control that is capable of
      * gaining focus will be tracked for certain keys that are
      * important to the underlying form (for example, PageUp,
      * PageDown, ScrollUp, ScrollDown etc.). Set it to
      * <code>false</code> if the control is not capable of gaining
      * focus or these particular key event are already used by the
      * control.
      */
     public void adapt(Control control, boolean trackFocus, boolean trackKeyboard) {
         control.setBackground(colors.getBackground());
         control.setForeground(colors.getForeground());
         if (control instanceof ExpandableComposite) {
             ExpandableComposite ec = (ExpandableComposite) control;
             if (ec.toggle != null) {
                 if (trackFocus)
                     ec.toggle.addFocusListener(visibilityHandler);
                 if (trackKeyboard)
                     ec.toggle.addKeyListener(keyboardHandler);
             }
             if (ec.textLabel != null) {
                 if (trackFocus)
                     ec.textLabel.addFocusListener(visibilityHandler);
                 if (trackKeyboard)
                     ec.textLabel.addKeyListener(keyboardHandler);
             }
             return;
         }
         if (trackFocus)
             control.addFocusListener(visibilityHandler);
         if (trackKeyboard)
             control.addKeyListener(keyboardHandler);
     }

     /**
      * Adapts a composite to be used in a form associated with this toolkit.
      *
      * @param composite
      * the composite to adapt
      */
     public void adapt(Composite composite) {
         composite.setBackground(colors.getBackground());
         composite.addMouseListener(new MouseAdapter() {
             public void mouseDown(MouseEvent e) {
                 ((Control) e.widget).setFocus();
             }
         });
         composite.setMenu(composite.getParent().getMenu());
     }

     /**
      * A helper method that ensures the provided control is visible when
      * ScrolledComposite is somewhere in the parent chain. If scroll bars are
      * visible and the control is clipped, the client of the scrolled composite
      * will be scrolled to reveal the control.
      *
      * @param c
      * the control to reveal
      */
     public static void ensureVisible(Control c) {
         FormUtil.ensureVisible(c);
     }

     /**
      * Creates a section as a part of the form.
      *
      * @param parent
      * the section parent
      * @param sectionStyle
      * the section style
      * @return the section widget
      */
     public Section createSection(Composite parent, int sectionStyle) {
         Section section = new Section(parent, orientation, sectionStyle);
         section.setMenu(parent.getMenu());
         adapt(section, true, true);
         if (section.toggle != null) {
             section.toggle.setHoverDecorationColor(colors
                     .getColor(IFormColors.TB_TOGGLE_HOVER));
             section.toggle.setDecorationColor(colors
                     .getColor(IFormColors.TB_TOGGLE));
         }
         section.setFont(boldFontHolder.getBoldFont(parent.getFont()));
         if ((sectionStyle & Section.TITLE_BAR) != 0
                 || (sectionStyle & Section.SHORT_TITLE_BAR) != 0) {
             colors.initializeSectionToolBarColors();
             section.setTitleBarBackground(colors.getColor(IFormColors.TB_BG));
             section.setTitleBarBorderColor(colors
                     .getColor(IFormColors.TB_BORDER));
             section.setTitleBarForeground(colors
                     .getColor(IFormColors.TB_TOGGLE));
         }
         return section;
     }

     /**
      * Creates an expandable composite as a part of the form.
      *
      * @param parent
      * the expandable composite parent
      * @param expansionStyle
      * the expandable composite style
      * @return the expandable composite widget
      */
     public ExpandableComposite createExpandableComposite(Composite parent,
             int expansionStyle) {
         ExpandableComposite ec = new ExpandableComposite(parent, orientation,
                 expansionStyle);
         ec.setMenu(parent.getMenu());
         adapt(ec, true, true);
         ec.setFont(boldFontHolder.getBoldFont(ec.getFont()));
         return ec;
     }

     /**
      * Creates a separator label as a part of the form.
      *
      * @param parent
      * the separator parent
      * @param style
      * the separator style
      * @return the separator label
      */
     public Label createSeparator(Composite parent, int style) {
         Label label = new Label(parent, SWT.SEPARATOR | style | orientation);
         label.setBackground(colors.getBackground());
         label.setForeground(colors.getBorderColor());
         return label;
     }

     /**
      * Creates a table as a part of the form.
      *
      * @param parent
      * the table parent
      * @param style
      * the table style
      * @return the table widget
      */
     public Table createTable(Composite parent, int style) {
         Table table = new Table(parent, style | borderStyle | orientation);
         adapt(table, false, false);
         // hookDeleteListener(table);
 return table;
     }

     /**
      * Creates a text as a part of the form.
      *
      * @param parent
      * the text parent
      * @param value
      * the text initial value
      * @return the text widget
      */
     public Text createText(Composite parent, String value) {
         return createText(parent, value, SWT.SINGLE);
     }

     /**
      * Creates a text as a part of the form.
      *
      * @param parent
      * the text parent
      * @param value
      * the text initial value
      * @param style
      * the text style
      * @return the text widget
      */
     public Text createText(Composite parent, String value, int style) {
         Text text = new Text(parent, borderStyle | style | orientation);
         if (value != null)
             text.setText(value);
         text.setForeground(colors.getForeground());
         text.setBackground(colors.getBackground());
         text.addFocusListener(visibilityHandler);
         return text;
     }

     /**
      * Creates a tree widget as a part of the form.
      *
      * @param parent
      * the tree parent
      * @param style
      * the tree style
      * @return the tree widget
      */
     public Tree createTree(Composite parent, int style) {
         Tree tree = new Tree(parent, borderStyle | style | orientation);
         adapt(tree, false, false);
         // hookDeleteListener(tree);
 return tree;
     }

     /**
      * Creates a scrolled form widget in the provided parent. If you do not
      * require scrolling because there is already a scrolled composite up the
      * parent chain, use 'createForm' instead.
      *
      * @param parent
      * the scrolled form parent
      * @return the form that can scroll itself
      * @see #createForm
      */
     public ScrolledForm createScrolledForm(Composite parent) {
         ScrolledForm form = new ScrolledForm(parent, SWT.V_SCROLL
                 | SWT.H_SCROLL | orientation);
         form.setExpandHorizontal(true);
         form.setExpandVertical(true);
         form.setBackground(colors.getBackground());
         form.setForeground(colors.getColor(IFormColors.TITLE));
         form.setFont(JFaceResources.getHeaderFont());
         return form;
     }

     /**
      * Creates a form widget in the provided parent. Note that this widget does
      * not scroll its content, so make sure there is a scrolled composite up the
      * parent chain. If you require scrolling, use 'createScrolledForm' instead.
      *
      * @param parent
      * the form parent
      * @return the form that does not scroll
      * @see #createScrolledForm
      */
     public Form createForm(Composite parent) {
         Form formContent = new Form(parent, orientation);
         formContent.setBackground(colors.getBackground());
         formContent.setForeground(colors.getColor(IFormColors.TITLE));
         formContent.setFont(JFaceResources.getHeaderFont());
         return formContent;
     }

     /**
      * Takes advantage of the gradients and other capabilities to decorate the
      * form heading using colors computed based on the current skin and
      * operating system.
      *
      * @since 3.3
      * @param form
      * the form to decorate
      */

     public void decorateFormHeading(Form form) {
         Color top = colors.getColor(IFormColors.H_GRADIENT_END);
         Color bot = colors.getColor(IFormColors.H_GRADIENT_START);
         form.setTextBackground(new Color[] { top, bot }, new int[] { 100 },
                 true);
         form.setHeadColor(IFormColors.H_BOTTOM_KEYLINE1, colors
                 .getColor(IFormColors.H_BOTTOM_KEYLINE1));
         form.setHeadColor(IFormColors.H_BOTTOM_KEYLINE2, colors
                 .getColor(IFormColors.H_BOTTOM_KEYLINE2));
         form.setHeadColor(IFormColors.H_HOVER_LIGHT, colors
                 .getColor(IFormColors.H_HOVER_LIGHT));
         form.setHeadColor(IFormColors.H_HOVER_FULL, colors
                 .getColor(IFormColors.H_HOVER_FULL));
         form.setHeadColor(IFormColors.TB_TOGGLE, colors
                 .getColor(IFormColors.TB_TOGGLE));
         form.setHeadColor(IFormColors.TB_TOGGLE_HOVER, colors
                 .getColor(IFormColors.TB_TOGGLE_HOVER));
         form.setSeparatorVisible(true);
     }

     /**
      * Creates a scrolled page book widget as a part of the form.
      *
      * @param parent
      * the page book parent
      * @param style
      * the text style
      * @return the scrolled page book widget
      */
     public ScrolledPageBook createPageBook(Composite parent, int style) {
         ScrolledPageBook book = new ScrolledPageBook(parent, style
                 | orientation);
         adapt(book, true, true);
         book.setMenu(parent.getMenu());
         return book;
     }

     /**
      * Disposes the toolkit.
      */
     public void dispose() {
         if (colors.isShared() == false) {
             colors.dispose();
             colors = null;
         }
         boldFontHolder.dispose();
     }

     /**
      * Returns the hyperlink group that manages hyperlinks for this toolkit.
      *
      * @return the hyperlink group
      */
     public HyperlinkGroup getHyperlinkGroup() {
         return hyperlinkGroup;
     }

     /**
      * Sets the background color for the entire toolkit. The method delegates
      * the call to the FormColors object and also updates the hyperlink group so
      * that hyperlinks and other objects are in sync.
      *
      * @param bg
      * the new background color
      */
     public void setBackground(Color bg) {
         hyperlinkGroup.setBackground(bg);
         colors.setBackground(bg);
     }

     /**
      * Refreshes the hyperlink colors by loading from JFace settings.
      */
     public void refreshHyperlinkColors() {
         hyperlinkGroup.initializeDefaultForegrounds(colors.getDisplay());
     }

     /**
      * Paints flat borders for widgets created by this toolkit within the
      * provided parent. Borders will not be painted if the global border style
      * is SWT.BORDER (i.e. if native borders are used). Call this method during
      * creation of a form composite to get the borders of its children painted.
      * Care should be taken when selection layout margins. At least one pixel
      * pargin width and height must be chosen to allow the toolkit to paint the
      * border on the parent around the widgets.
      * <p>
      * Borders are painted for some controls that are selected by the toolkit by
      * default. If a control needs a border but is not on its list, it is
      * possible to force border in the following way:
      *
      * <pre>
      *
      *
      *
      * widget.setData(FormToolkit.KEY_DRAW_BORDER, FormToolkit.TREE_BORDER);
      *
      * or
      *
      * widget.setData(FormToolkit.KEY_DRAW_BORDER, FormToolkit.TEXT_BORDER);
      *
      *
      *
      * </pre>
      *
      * @param parent
      * the parent that owns the children for which the border needs
      * to be painted.
      */
     public void paintBordersFor(Composite parent) {
         // if (borderStyle == SWT.BORDER)
 // return;
 if (borderPainter == null)
             borderPainter = new BorderPainter();
         parent.addPaintListener(borderPainter);
     }

     /**
      * Returns the colors used by this toolkit.
      *
      * @return the color object
      */
     public FormColors getColors() {
         return colors;
     }

     /**
      * Returns the border style used for various widgets created by this
      * toolkit. The intent of the toolkit is to create controls with styles that
      * yield a 'flat' appearance. On systems where the native borders are
      * already flat, we set the style to SWT.BORDER and don't paint the borders
      * ourselves. Otherwise, the style is set to SWT.NULL, and borders are
      * painted by the toolkit.
      *
      * @return the global border style
      */
     public int getBorderStyle() {
         return borderStyle;
     }

     /**
      * Returns the margin required around the children whose border is being
      * painted by the toolkit using {@link #paintBordersFor(Composite)}. Since
      * the border is painted around the controls on the parent, a number of
      * pixels needs to be reserved for this border. For windowing systems where
      * the native border is used, this margin is 0.
      *
      * @return the margin in the parent when children have their border painted
      * @since 3.3
      */
     public int getBorderMargin() {
         return getBorderStyle() == SWT.BORDER ? 0 : 2;
     }

     /**
      * Sets the border style to be used when creating widgets. The toolkit
      * chooses the correct style based on the platform but this value can be
      * changed using this method.
      *
      * @param style
      * <code>SWT.BORDER</code> or <code>SWT.NULL</code>
      * @see #getBorderStyle
      */
     public void setBorderStyle(int style) {
         this.borderStyle = style;
     }

     /**
      * A utility method that ensures that the control is visible in the scrolled
      * composite. The prerequisite for this method is that the control has a
      * class that extends ScrolledComposite somewhere in the parent chain. If
      * the control is partially or fully clipped, the composite is scrolled to
      * set by setting the origin to the control origin.
      *
      * @param c
      * the control to make visible
      * @param verticalOnly
      * if <code>true</code>, the scrolled composite will be
      * scrolled only vertically if needed. Otherwise, the scrolled
      * composite origin will be set to the control origin.
      * @since 3.1
      */
     public static void setControlVisible(Control c, boolean verticalOnly) {
         ScrolledComposite scomp = FormUtil.getScrolledComposite(c);
         if (scomp == null)
             return;
         Point location = FormUtil.getControlLocation(scomp, c);
         scomp.setOrigin(location);
     }

     private void initialize() {
         initializeBorderStyle();
         hyperlinkGroup = new HyperlinkGroup(colors.getDisplay());
         hyperlinkGroup.setBackground(colors.getBackground());
         visibilityHandler = new VisibilityHandler();
         keyboardHandler = new KeyboardHandler();
         boldFontHolder = new BoldFontHolder();
     }

     private void initializeBorderStyle() {
         String osname = System.getProperty("os.name"); //$NON-NLS-1$
 String osversion = System.getProperty("os.version"); //$NON-NLS-1$
 if (osname.startsWith("Windows") && "5.1".compareTo(osversion) <= 0) { //$NON-NLS-1$ //$NON-NLS-2$
 // Skinned widgets used on newer Windows (e.g. XP (5.1), Vista
 // (6.0))
 // Check for Windows Classic. If not used, set the style to BORDER
 RGB rgb = colors.getSystemColor(SWT.COLOR_WIDGET_BACKGROUND);
             if (rgb.red != 212 && rgb.green != 208 && rgb.blue != 200)
                 borderStyle = SWT.BORDER;
         } else if (osname.startsWith("Mac")) //$NON-NLS-1$
 borderStyle = SWT.BORDER;
     }

     /**
      * Returns the orientation that all the widgets created by this toolkit will
      * inherit, if set. Can be <code>SWT.NULL</code>,
      * <code>SWT.LEFT_TO_RIGHT</code> and <code>SWT.RIGHT_TO_LEFT</code>.
      *
      * @return orientation style for this toolkit, or <code>SWT.NULL</code> if
      * not set. The default orientation is inherited from the Window
      * default orientation.
      * @see org.eclipse.jface.window.Window#getDefaultOrientation()
      * @since 3.1
      */

     public int getOrientation() {
         return orientation;
     }

     /**
      * Sets the orientation that all the widgets created by this toolkit will
      * inherit. Can be <code>SWT.NULL</code>, <code>SWT.LEFT_TO_RIGHT</code>
      * and <code>SWT.RIGHT_TO_LEFT</code>.
      *
      * @param orientation
      * style for this toolkit.
      * @since 3.1
      */

     public void setOrientation(int orientation) {
         this.orientation = orientation;
     }
 }

